function [linInd] = partsub2ind(arraySize, partDims, partDimSubs)
%PARTSUB2IND 将下标索引转换为线性索引，支持仅输入部分维度的下标（sub2ind的部分输入版本）
%
% Input Arguments
% # arraySize: 向量，数组尺寸
% # partDims: 长度为m向量，指定下标的维数
% # partDimSubs: 行数为m的矩阵，各行对应partDims的各维数，每行元素为对应维数的下标，不足的元素设置为NaN（未指定的维数包含全部下标）
%
% Output Arguments
% linInd: 长度为s1*s2*...*sm的行向量，其中si为各维数的下标数量（未指定的维数为该维数长度），各下标索引对应的线性索引，顺序为靠后维数的索引先变化

% NOTE: 本函数使用线性索引
nDim = length(arraySize);
dimSubs = NaN(nDim, max(arraySize));
nDimSubs = NaN(1, nDim);
for i=1:length(partDims)
    nDimSubs(partDims(i)) = length(partDimSubs(i, :));
    dimSubs(partDims(i), 1:nDimSubs(partDims(i))) = partDimSubs(i, :);
end
nonPartDims = setdiff(1:nDim, partDims);
for i=1:length(nonPartDims)
    nDimSubs(nonPartDims(i)) = arraySize(nonPartDims(i));
    dimSubs(nonPartDims(i), 1:arraySize(nonPartDims(i))) = 1:arraySize(nonPartDims(i));
end
sizeCP = [1 cumprod(arraySize(:)')];
linInd = recurse(prod(nDimSubs), dimSubs, nDimSubs, sizeCP);
end

function [linInd] = recurse(linIndLen, dimSubs, nDimSubs, sizeCP)
if ~isempty(dimSubs) && ~isempty(nDimSubs)
    linInd = zeros(1, linIndLen);
    lenPerSub = linIndLen / nDimSubs(1);
    for i=1:nDimSubs(1)
        subInd = 1 + ((i-1)*lenPerSub):(i*lenPerSub);
        linInd(subInd) = (dimSubs(1, i)-1)*sizeCP(1) + recurse(lenPerSub, dimSubs(2:end, :), nDimSubs(2:end), sizeCP(2:end)); % NOTE: 假设MATLAB使用列优先索引
    end
else
    linInd = 1;
end
end